#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from dialogs import *
import os
import tarfile

import scribu

################################
########## MmWindow ############
################################

sqlIcon=["16 14 5 1",
			" 	c None",
			".	c black",
			"X	c gray50",
			"o	c lightyellow",
			"O	c yellow",
			"                 ",
			"                 ",
			" XX    XX    X   ",
			"X  X  X  X   X   ",
			"X    X    X  X   ",
			" X   X    X  X   ",
			"  X  X    X  X   ",
			"   X X  X X  X   ",
			"X  X  X  X   X   ",
			" XX    XX X  XXX ",
			"                 ",
			"                 ",
			"                 ",
			"                 ",
			"                 "
             ]

class MmWindow(QMainWindow):

	DATA_SOURCE_TYPE = None
	STATUS = {"typ": "", 
			"database": "",
			 "user": "",
			  "passw": '',
			   "table": "",
			    "file": ""}
######## INIT HLAVNIHO OKNA #########
	
	def __init__(self, *args):
		apply(QMainWindow.__init__, (self,) + args)
		self.setGeometry(30, 30, 650,400)
		self.setCaption("Mail Merge for Scribus")
		
		self.dialog = None
		self.fileName = ""
		self.charset = "utf8"
		self.open_file_data = None
		self.query = ""
		
# menu
		self.initMenuBar()
		self.initToolBar()
		self.initStatusBar()
		
		self.grid = QGrid(3, self)
		self.grid.setFrameShape(QFrame.StyledPanel)
		self.grid.setSpacing(5)
		self.grid.setMargin(5)
		
# tabulka
		self.table = QTable(100, 10, self.grid)
		self.table.NotEditing
		self.connect(self.table, SIGNAL("clicked(int, int, int, const QPoint&)"), self.printTabPos)
		self.connect(self.table.horizontalHeader(), SIGNAL("clicked(int)"), self.printColumnTag)

# box s tlacitky a popisky vpravo
		self.rightButtonBox = QVBox(self.grid)
		self.rightButtonBox.setSpacing(5)
		self.rightButtonBox.setMargin(10)
		self.rightButtonBox.setMaximumHeight(240)
		
# labely vpravo
		self.labelGroupBox = QGrid(2, self.rightButtonBox)
		self.labelGroupBox.setMaximumHeight(150)
		self.labelGroupBox.setMargin(5)
		self.labelGroupBox.setPaletteBackgroundColor(QColor("lightyellow"))
		self.labelGroupBox.show()
		
		QLabel("", self.rightButtonBox)
		
		self.l1 = QLabel("DB Type: ", self.labelGroupBox)
		self.DBSType = QLabel("None", self.labelGroupBox)
		self.l5 =QLabel("File: ", self.labelGroupBox)
		self.DBSFile = QLabel("None", self.labelGroupBox)
		self.l2 =QLabel("Database: ", self.labelGroupBox)
		self.DBSDatabase = QLabel("None", self.labelGroupBox)
		self.l3 =QLabel("User: ", self.labelGroupBox)
		self.DBSUser = QLabel("None", self.labelGroupBox)
		self.l4 =QLabel("Table: ", self.labelGroupBox)
		self.DBSTable = QLabel("None", self.labelGroupBox)
		
		self.updateInfo()
		
# tlacitka vpravo
		self.getDataButton = QPushButton(QIconSet(QPixmap(ICONS + "vcs_commit.png")), "Get data", self.rightButtonBox)
		self.connect(self.getDataButton, SIGNAL("clicked()"), self.slotGetDataSource)
		
		self.runButton = QPushButton(QIconSet(QPixmap(ICONS + "gear.png")), "Run MailMerge", self.rightButtonBox)
		self.connect(self.runButton, SIGNAL("clicked()"), self.slotRun)
		self.runButton.setFocus()
		
		##self.okButton = QPushButton("OK", self.rightButtonBox)
## bude nastaven jako vychozi
		##self.okButton.setFocus()
		
		self.cancelButton = QPushButton(QIconSet(QPixmap(ICONS + "cancel.png")), "Quit", self.rightButtonBox)
		self.connect(self.cancelButton, SIGNAL("clicked()"), self.close)

		self.setCentralWidget(self.grid)

	def initMenuBar(self):
		"""
		Vytvori menu
		"""
		
		self.menu = [
			("&File",
				[("&Open...", self.slotOpenFile, QIconSet(QPixmap(ICONS + "fileopen.png")), Qt.CTRL+Qt.Key_O),
				("&Save", self.slotSaveFile, QIconSet(QPixmap(ICONS + "filesave.png")), Qt.CTRL+Qt.Key_S),
				("Save &as...", self.slotSaveAs, QIconSet(QPixmap(ICONS + "filesaveas.png"))),
				(None,),
				("&Quit", self.close, QIconSet(QPixmap(ICONS + "cancel.png")), Qt.CTRL + Qt.Key_Q)]),
			("&Settings",
				[("Select &Datasource", self.mainSettingDialog, QIconSet(QPixmap(ICONS + "configure.png")), Qt.CTRL+Qt.Key_D),
				("Set SQL qu&ery", self.showSqlDialog, QIconSet(QPixmap(sqlIcon)), Qt.CTRL + Qt.Key_L)]),
			("&Run",
				[("&Get data", self.slotGetDataSource, QIconSet(QPixmap(ICONS + "vcs_commit.png")), Qt.CTRL+Qt.Key_G),
				("&Run mailmerge", self.slotRun, QIconSet(QPixmap(ICONS + "gear.png")), Qt.CTRL+Qt.Key_R),
				(None,),
				("&Tar Files", self.slotTarFiles, QIconSet(QPixmap(ICONS + "tar.png")), Qt.CTRL + Qt.Key_T)
				]),
			("&Help",
				[("&About", self.about, QIconSet(QPixmap(ICONS + "emoticon.png")), Qt.CTRL + Qt.Key_A),
				("About &QT", self.aboutQT)])
			]
			
		for (menuName, subMenu) in self.menu:
			menu = QPopupMenu(self)
			self.menuBar().insertItem( menuName, menu )
			for menuOption in subMenu:
				if len(menuOption) == 1:
					menu.insertSeparator()
				elif len(menuOption) == 2:
					menu.insertItem(menuOption[0], menuOption[1] )
				elif len(menuOption) == 3:
					menu.insertItem(menuOption[2], \
									menuOption[0], \
									menuOption[1] )
				elif len(menuOption) == 4:
					menu.insertItem(menuOption[2], \
									menuOption[0], \
									menuOption[1], \
									menuOption[3])
		
		

	def initToolBar(self):
		self.ToolBar = QToolBar(self)
		
		self.SaveToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "filesave.png")
		self.SaveToolButton.setPixmap(pixmap)
		self.connect(self.SaveToolButton, SIGNAL("clicked()"), self.slotSaveFile)
		
		self.SaveAsToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "filesaveas.png")
		self.SaveAsToolButton.setPixmap(pixmap)
		self.connect(self.SaveAsToolButton, SIGNAL("clicked()"), self.slotSaveAs)
		
		self.FileOpenToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "fileopen.png")
		self.FileOpenToolButton.setPixmap(pixmap)
		self.connect(self.FileOpenToolButton, SIGNAL("clicked()"), self.slotOpenFile)
		
		self.ToolBar.addSeparator()
		
		self.SqlToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(sqlIcon)
		self.SqlToolButton.setPixmap(pixmap)
		self.connect(self.SqlToolButton, SIGNAL("clicked()"), self.showSqlDialog)
		
		self.PrefToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "configure.png")
		self.PrefToolButton.setPixmap(pixmap)
		self.connect(self.PrefToolButton, SIGNAL("clicked()"), self.mainSettingDialog)
		
		self.ToolBar.addSeparator()
		
		self.PackToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "tar.png")
		self.PackToolButton.setPixmap(pixmap)
		self.connect(self.PackToolButton, SIGNAL("clicked()"), self.slotTarFiles)
		
		self.QueryToolButton = QToolButton(self.ToolBar)
		pixmap = QPixmap(ICONS + "1rightarrow.png")
		self.QueryToolButton.setPixmap(pixmap)
		self.connect(self.QueryToolButton, SIGNAL("clicked()"), self.trySqlQuery)
		self.QueryToolButton.setDisabled(1)
		
		
	def initStatusBar(self):
		"""
		Inicializuje statusBar
		"""
		self.statusBar().message("Mail merge is Ready... :o)")
	
	def setDataSrcType(self, tp):
		"""
		Nastavuje datovy typ na parametr tp.
		"""
		self.DATA_SOURCE_TYPE = tp
		return self.DATA_SOURCE_TYPE
	
	def setStatus(self, st):
		pass
	
############################################# SLOTY #############################################

	def slotOpenFile(self):
		fileName = str(QFileDialog.getOpenFileName("Mail merge file", "*.mm", self))
		print fileName
		if not fileName=="":
			self.load(fileName)
		else:
			self.statusBar().message("Loading aborted", 4000)
			
	def load(self, fileName):
		f = open(fileName, "r")
		if f:
			self.open_file_data = eval(f.read())
			self.slotGetDataSource(1)
			self.fileName = fileName
			self.statusBar().message("Loaded document " + fileName, 4000)
		else:
			self.statusBar().message("Could not load " + fileName, 5000)
			return

	def slotSaveFile(self):
		if self.fileName=="":
			self.slotSaveAs()
			return
		self.save()

	def save(self):
		if self.fileName=="":
			self.slotSaveAs()
			return
		text = str(self.DATA_SOURCE_TYPE.data)
		try:
			f = open(self.fileName, "w")
			f.write(text)
		except:
			self.statusBar().message("Could not write to " + self.fileName)
			f.close()
			return
		f.close()


	def slotSaveAs(self):
		fileName = str(QFileDialog.getSaveFileName("Mail merge file1.mm", "*.mm", self))
		if fileName != "":
			self.fileName = fileName
			self.save()
		else:
			self.statusBar().message("Saving aborted", 2000)
	
	def updateInfo(self):
		"""
		Vykresluje aktualni nastaveni
		"""
		self.DBSType.setText(self.STATUS["typ"])
		
		if "SQL" in self.STATUS["typ"]:
			self.DBSDatabase.setText(self.STATUS["database"])
			self.DBSDatabase.show()
			self.DBSUser.setText(self.STATUS["user"])
			self.DBSUser.show()
			self.DBSTable.setText(self.STATUS["table"])
			self.DBSTable.show()
			self.l2.show()
			self.l3.show()
			self.l4.show()
			self.l5.hide()
			self.DBSFile.hide()
			self.QueryToolButton.setEnabled(1)
		else:
			self.l2.hide()
			self.DBSDatabase.hide()
			tmp = split(self.STATUS["file"], '/')
			self.DBSFile.setText(tmp[-1])
			self.l3.hide()
			self.DBSUser.hide()
			self.l4.hide()
			self.DBSTable.hide()
			self.l5.show()
			self.DBSFile.show()
			self.QueryToolButton.setEnabled(0)

	def slotGetDataSource(self, from_file=None):
		"""
		Reaguje na tlacitko 'Get data source'
		a provadi cinnosti:
			- zkontroluje, zda je vybran typ datoveho zdroje,
			- spoji se s nim,
			- precte data,
			- vykresli je do tabulky.
		"""
		
		self.clearTable()
		
		if self.DATA_SOURCE_TYPE == None:
			QMessageBox.warning(self, "Warrning", "Your DataSource is \"None\"!")

		try:
			source = None
			if not from_file:
				if self.query and "SQL" in self.STATUS["typ"] and upper(split(self.query, ' ')[0]) == "SELECT":
					try:
						self.DATA_SOURCE_TYPE.read(self.query)
					except:
						#QMessageBox.critical(self, "Critical", "Bad SQL query or databaze error.")
						pass
				else:
					self.DATA_SOURCE_TYPE.read()
				source = self.DATA_SOURCE_TYPE.data
			else:
				source = self.open_file_data
		
# vykresleni ziskanych dat do tabulky
			self.table.setNumCols(len(source[0]) + 1)
			self.table.setNumRows(len(source) + 1)
		
			for i in range(len(source)):
				for j in range(len(source[i])):
					self.table.setText(i, j, unicode(str(source[i][j]), self.charset))
			
# nastavi hlavicky tabulky
			if not from_file:
				headers = self.DATA_SOURCE_TYPE.get_items()
			else:
				headers = self.open_file_data[0]
			for i in range(len(source[0])):
					self.table.horizontalHeader().setLabel(i, headers[i])
					
		except:
			QMessageBox.critical(self, "Error", "Sorry, database/file error ...")

	def clearTable(self):
		"""
		vycisti predchozi zaznamy a hlavicky nastavi na cisla
		"""
		for i in range(self.table.numCols()):
			self.table.horizontalHeader().setLabel(i, str(i))
			for j in range(self.table.numRows()):
				self.table.clearCell(i, j)
				
	def slotTarFiles(self):
		pass
	
########### DIALOGOVA OKNA #############

	def about(self):
		QMessageBox.information(self, "About", u"<center><h3>Mail Merge.</h3>Autor: Bohuslav Ječmen,<br> PřF, UPOL, 2007</center>")
		
	def aboutQT(self):
		QMessageBox.aboutQt(self, "About Qt")

	def mainSettingDialog(self):
		if not self.dialog:
			self.dialog = settingDialog(self, "Settings", TRUE)
			self.dialog.STATUS = self.STATUS
		self.connect(self.dialog, PYSIGNAL("sigSetSrcType"), self.setDTfromDialog)
		self.connect(self.dialog, PYSIGNAL("sigSetting"), self.setDTfromDialog)
		self.connect(self.dialog, PYSIGNAL("sigPreferences"), self.setPreffromDialog)
		self.connect(self.dialog, PYSIGNAL("sigEncoding"), self.setEncodingfromDialog)

		self.dialog.show()
		self.statusBar().message("Settings", 4000)
		
		
	def setDTfromDialog(self):
		self.DATA_SOURCE_TYPE = self.dialog.driver
		self.STATUS = self.dialog.STATUS
		self._setDSObjectStatus()
		print "current status: ", self.STATUS
		print self.DATA_SOURCE_TYPE
		
		self.statusBar().message("New setting for: " + str(self.STATUS["typ"]), 4000)
		self.updateInfo()
		
	def setPreffromDialog(self):
		self.statusBar().message("Preferences saved.", 4000)
		
	def setEncodingfromDialog(self):
		self.charset = self.dialog.current_encoding
		self.statusBar().message("Current encoding will be: " + self.charset, 4000)
		
	def showSqlDialog(self):
		self.sqldeditor = sqlDialog(self)
		self.sqldeditor.show()
		self.connect(self.sqldeditor, PYSIGNAL("sigSqlQuerySelect"), self.setQuery)
		self.connect(self.sqldeditor, PYSIGNAL("sigExSqlQuery"), self.setQuery)
		
	def setQuery(self):
		self.query = self.sqldeditor.query
	
	
	def trySqlQuery(self):
		print self.DATA_SOURCE_TYPE.execute(self.query)
	
######### DALSI FUNKCE ############
		
	def _setDSObjectStatus(self):
		"""
		Uklada konfiguraci ze
		self.STATUS do vytvoreneho mm_ objektu.
		"""
		if "SQL" in self.STATUS["typ"]:
			s = self.STATUS
			
			self.DATA_SOURCE_TYPE.set_status(dbtype=s["typ"], user=s["user"], password=s["passw"], database=s["database"], table=s["table"])
		else:
			self.DATA_SOURCE_TYPE.set_status(self.STATUS["file"])
			
################################## PRACE SE SCRIBUSEM ######################################
	
	
	def printTabPos(self, a, b, c, d):
		pass
		
	def printColumnTag(self, a):
		"""
		Prints tag into selected Text Frame, if on table header is clicked.
		"""
		header = '<' + str(self.table.horizontalHeader().label(a)) + '>'
		text = unicode(str(header), self.charset)

		if scribu.whatIsTheObject() != 4:
			QMessageBox.warning(self, "Warrning", "Select text frame!")
			return
		else:
			scribu.sInsertText(text, -1)
			scribu.sRedrawAll()
	
	def slotRun(self):
		"""
		Prints data ito the selected Text Frame, makes copies.
		"""
		self.statusBar().message("Working, wait ...")
		
		user_dir = os.path.expanduser('~')
		working_dir = user_dir + "/.scribus/mailmerge/"
		
		if not self.dialog.tarpath:
			if not os.path.isdir(working_dir):
				os.mkdir(working_dir)
		else:
			working_dir = self.dialog.tarpath
		
		scribu.sSaveDocAs(working_dir + "MailMergeOriginal.sla")
		scribu.sDocChanged(1)
		np = scribu.sPageCount()
		page_parsed_data = []
		all_text_frames = []

		for page in range(np):
			scribu.sGotoPage(page + 1)
			frames_parsed_data = []
			
			text_frames = scribu.onlyTxtFrame()
			all_text_frames.append(text_frames)
			text_frames_properties = scribu.getObjectsPreferences(text_frames, text=1)

			for fr in text_frames:
				curr_frame = []
				tags, text_without_tags = scribu.parseTags(text_frames_properties[fr]["text"], self.DATA_SOURCE_TYPE.get_items())
				indexes = map(lambda x: self.DATA_SOURCE_TYPE.get_items().index(x), tags)
				curr_frame.append(tags)
				curr_frame.append(text_without_tags)
				curr_frame.append(indexes)
				frames_parsed_data.append(curr_frame)
				curr_frame = []
			page_parsed_data.append(frames_parsed_data)

		nr = 1
		print page_parsed_data
		
		for item in self.DATA_SOURCE_TYPE.data:

			doc_name = working_dir + "newmm" + str(nr) + ".sla"
			scribu.sSaveDocAs(doc_name)

			for page in range(np):
				scribu.sGotoPage(page + 1)
				text_frames = all_text_frames[page]
				frames_parsed_data = page_parsed_data[page]
				print text_frames
				for fr in text_frames:
					n = text_frames.index(fr)
					
					text_without_tags = frames_parsed_data[n][1]
					indexes = frames_parsed_data[n][2]
				
					name = fr
					scribu.sDeleteText(name)
						
					indexes_iterator = iter(indexes)
						
					for i in text_without_tags:
						
						curr_text = unicode(str(i), self.charset)
						if i == "#MailMergeTag#":
							try:
								curr_text = unicode(str(item[indexes_iterator.next()]), self.charset)
							except StopIteration:
								pass
						scribu.sInsertText(curr_text, -1, str(name))
						
			nr += 1
			scribu.sSaveDoc()
		scribu.sCloseDoc()
		scribu.sOpenDoc(working_dir + "MailMergeOriginal.sla")
			
		scribu.sRedrawAll()
		self.statusBar().message("Done", 4000)
				

############################################
############## NETRIDNI F-CE ###############
############################################

def main(args):
	app=QApplication(args)
	win=MmWindow()
	app.setMainWidget(win)
	win.show()
	app.exec_loop()

# naloaduje aplikaci MailMerge do menu Extensions
def getExtensionsMenu():
	mainWidget = qApp.mainWidget()
	menus = mainWidget.queryList("QPopupMenu", "extensionsMenu")
	if menus:
		extensionsMenu = menus[0]
	else:
		extensionsMenu = QPopupMenu(mainWidget, "extensionsMenu")
		try:
			menuBar = mainWidget.menuBar()
		except AttributeError:
			menuBar = mainWidget.queryList("QMenuBar", None, True, False)[0]
		menuBar.insertItem("Extensions", extensionsMenu, -1, menuBar.count()-1)
	return extensionsMenu



def checkState():
	if not scribu.sHaveDoc():
		try:
			scribu.sNewDocument(scribu.sPAPER_A4, (10, 10, 20, 20), scribu.sLANDSCAPE, 1, scribu.sUNIT_POINTS, scribu.sFACINGPAGES, scribu.sFIRSTPAGERIGHT)
		except:
			scribu.sNewDocument(scribu.sPAPER_A4, (10, 10, 20, 20), scribu.sPORTRAIT, 1, scribu.sUNIT_POINTS, scribu.sNOFACINGPAGES, scribu.sFIRSTPAGERIGHT, 1)
	
	all_objects = scribu.sGetPageItems()
	text = 0
	
	for object in all_objects:
		if object[1] == 4:
			text = 1
			break
		
	if not text:
		scribu.sCreateText(20, 30, 100, 50)

checkState()

try:
	spy = MmWindow(qApp.mainWidget())
	getExtensionsMenu().insertItem("PyQt MailMerge", spy.show)

except:
	import sys
	try:
		qApp.children()
		win = MmWindow()
		win.show()
	except:
		main(sys.argv)

##if __name__=="__main__":
	##main(sys.argv)



#def main(args):
	#app=QApplication(args)
	#win=MmWindow()
	#win.show()
	#app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
	#app.exec_loop()

#if __name__=="__main__":
	#main(sys.argv)